#include "SendImgMsg.h"

#include <cstring>
#include <QBuffer>

#include "NetHeader.h"

extern QUEUE_DATA<MESG> g_sendQueue;

SendImgMsg::SendImgMsg(QObject *parent)
    : QThread{parent}
{}

void SendImgMsg::pushToQueue(QImage imge)
{
    QByteArray byte;
    QBuffer buf(&byte);
    buf.open(QIODevice::WriteOnly);
    imge.save(&buf, "JPEG");
    QByteArray ss = qCompress(byte);
    QByteArray vv = ss.toBase64();
    m_queueLock.lock();
    while (m_imgQueue.size() > MAX_QUEUE_DATA_COUNT) {
        m_queueWaitCond.wait(&m_queueLock);
    }
    m_imgQueue.push_back(vv);
    m_queueLock.unlock();
    m_queueWaitCond.wakeOne();
}

void SendImgMsg::imageCapture(QImage imge)
{
    pushToQueue(imge);
}

void SendImgMsg::clearImgQueue()
{
    QMutexLocker locker(&m_queueLock);
    m_imgQueue.clear();
}

void SendImgMsg::stopImmediately()
{
    QMutexLocker locker(&m_lock);
    m_isRun = false;
}

void SendImgMsg::run()
{
    m_isRun = true;
    while (true) {
        m_queueLock.lock();

        while (m_imgQueue.size() == 0) {
            bool flag = m_queueWaitCond.wait(&m_queueLock, WAITSECONDS * 1000);
            if (!flag) {
                QMutexLocker locker(&m_lock);
                if (!m_isRun) {
                    m_queueLock.unlock();
                    return;
                }
            }
        }

        QByteArray img = m_imgQueue.front();
        m_imgQueue.pop_front();
        m_queueLock.unlock();
        m_queueWaitCond.wakeOne();

        try{
            auto imgSend = new MESG;
            memset(imgSend, 0, sizeof(MESG));
            imgSend->type = MsgType_ImgSend;
            imgSend->size = img.size();

            try{
                imgSend->data.reset(new uchar[imgSend->size]);
                memset(imgSend->data.get(), 0, imgSend->size);
                memcpy_s(imgSend->data.get(), imgSend->size, img.data(), img.size());
                g_sendQueue.push_msg(imgSend);

            } catch (std::bad_alloc& msgError) {
                delete imgSend;
                LOG << "new msg->data error" << msgError.what();
            }
        } catch (std::bad_alloc& msgError) {
            LOG << "new msg error" << msgError.what();
        }
    }
}

